import serial
import sys

BIN_FNAME = 'ledpanel.bin'
COM_PORT_NUM = 2
DEBUG = True

def log(message):
    sys.stdout.write(message + '\n')
    sys.stdout.flush()

def logDebug(message):
    if DEBUG: log('DBG: ' + message)
def logInfo(message):   log('INF: ' + message)
def logError(message):  log('ERR: ' + message)

ANSWER_BUFF_01 = '\x48\x44\x00\x0d\x00\x00\x3a\xb3\x0f\x01\x01\x96\xaa'
ANSWER_BUFF_02 = '\x48\x44\x00\x0f\x0c\x00\x87\xd8\x0a\x01\x00\x00\x02\x11\xaa'
ANSWER_BUFF_03 = '\x48\x44\x00\x0f\x0c\x00\x67\x0e\x0b\x01\x00\x01\x01\x29\xaa\x48\x44\x00\x0f\x0c\x00\x67\x0e\x0b\xab\x00\x01\x01\xd3\xaa'

class AccumulatedEvent:
    def __init__(self):
        self.clear()

    def clear(self):
        self.state = 0 #0 - nothing received, 1 - one 0x91 received, 2 - 0x92 received

    def accumulate(self, buff, conn):
        if self.state != 2 and (str(buff[0]) != str('\x48') or str(buff[1]) != str('\x44')):
            logError('accumulate: buff[0] is not valid: ' + str(buff[0:1]))
            return
        while True:
            if self.state == 0 and str(buff[3]) == str('\x14'):
                self.state = 1
                logDebug('accumulate: received init #1')
                while True:
                    tmp = conn.readline()
                    if tmp != '': continue
                    break
                conn.write(ANSWER_BUFF_01)
                return
            if self.state == 1 and str(buff[3]) == str('\xdc'):
                self.state = 2
                logDebug('accumulate: received init #2')
                while True:
                    tmp = conn.readline()
                    if tmp != '': continue
                    break
                conn.write(ANSWER_BUFF_02)
                return
            #if self.state == 2 and str(buff[3]) == str('\x2e'):
            if self.state == 2:
                self.clear()
                while True:
                    tmp = conn.readline()
                    if tmp != '':
                        buff = buff + tmp
                        continue
                    break
                size    = len(buff)
                logInfo('accumulate: received bitmap %d bytes' % (size))
                size01  = size & 0x00FF
                size02  = (size & 0xFF00) >> 8
                extbuff = chr(size01) + chr(size02) + buff
                f = open(BIN_FNAME, 'wb')
                f.write(extbuff)
                f.close()
                logInfo('accumulate: written bin file "%s"' % (BIN_FNAME))
                conn.write(ANSWER_BUFF_03)
                logInfo('accumulate: aknowledge sent')
                return
            if str(buff[3]) == str('\x14'):
                self.clear()
                continue
            logError('accumulate: unexpected buffer[%s]: %s' % (str(buff[1]),str(buff)))
            return
            break

def main():
    p = serial.Serial(port=COM_PORT_NUM - 1, baudrate=1200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=5)
    e = AccumulatedEvent()
    logInfo('port %d is opened' % (COM_PORT_NUM))

    while True:
        try:

            d = p.readline()
            if d == '': continue
            logDebug('something received from port ...')
            e.accumulate(d, p)

        except Exception, err:
            logError('main: ' + str(err))
            continue

    p.close()
    logInfo('port %d is closed' % (COM_PORT_NUM - 1))


if __name__ == '__main__': main()
